#ifndef LEAMSTREAMHH
#define LEAMSTREAMHH
#include "stdincludes.hh"
#include "leam-typedefs.hh"
#include "leam-in-stream.hh"
#include "leam-out-stream.hh"
#include "leam-data-in-stream.hh"
#include "leam-data-out-stream.hh"
#include "leam-handler.hh"


namespace leam
{
    typedef std::pair<TMessageId,LeamDataOutStream*> TBeginMessageReturn;
    
    //system->leam iface
    class LeamStream
    {
	LeamStream( const LeamStream& other );
	LeamStream& operator=( const LeamStream& other );

    protected:
	TMessageId curId;
	TMessageIdVector unAck;
	TMessageIdVector unFin;
	licada::TDataVector dataBuffer;
	std::string stackTrace;
	ILeamInStream* inStream;
	ILeamOutStream* outStream;
	LeamDataInStream dataIn;
	LeamDataOutStream dataOut;
	ILeamHandler* handler;
	
    public:
	//initialize member variables and curId to zero.
	LeamStream( ILeamInStream* _inStream = NULL
		    , ILeamOutStream* _outStream = NULL
		    , ILeamHandler* _handler = NULL
		    , bool checkVersion = true );

	void setup( ILeamInStream* _inStream = NULL
		    , ILeamOutStream* _outStream = NULL
		    , ILeamHandler* _handler = NULL
		    , bool checkVersion = true );
	virtual ~LeamStream();
	//Send a message of this length.  Obviously, you need to know
	//the length you are sending.
	virtual  TBeginMessageReturn beginSendMessage( TLength length );
	//Wait for the next bit of communication.  This immediately
	//causes a read, so the behavior of your particular in stream
	//implementation will dicate the parameters of this call.
	virtual void readNext();
	//readNext until hasData returns false.
	virtual void readAll();
	//Queries whether a message was acknowledged Keep in mind that
	//the message id increments, and all this does is see if the
	//message is the unacknowledged list.
	virtual bool isAck( TMessageId msg );
	//Queries whether a message is finished processing
	virtual bool isFin( TMessageId msg );
	//close in and out streams, tell handler we are closed
	virtual void close();

    protected:
	virtual void handleError(TMessageId msgId);
    };
}
#endif
